home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-11-12 | 54.9 KB | 2,815 lines |
- Newsgroups: comp.sources.misc
- From: sjg@zen.void.oz.au (Simon J. Gerraty)
- Subject: v25i051: pdksh - Public Domain Korn Shell, v4, Part05/09
- Message-ID: <1991Nov13.031141.16071@sparky.imd.sterling.com>
- X-Md4-Signature: caab833c4db7863094df7fd7ea6c1d2f
- Date: Wed, 13 Nov 1991 03:11:41 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: sjg@zen.void.oz.au (Simon J. Gerraty)
- Posting-number: Volume 25, Issue 51
- Archive-name: pdksh/part05
- Environment: UNIX
-
- #! /bin/sh
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: sh/c_sh.c sh/c_test.c sh/edit.c sh/history.c sh/main.c
- # sh/tree.c std/stdc/stdio.c
- # Wrapped by kent@sparky on Tue Nov 12 20:44:33 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 5 (of 9)."'
- if test -f 'sh/c_sh.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sh/c_sh.c'\"
- else
- echo shar: Extracting \"'sh/c_sh.c'\" \(8560 characters\)
- sed "s/^X//" >'sh/c_sh.c' <<'END_OF_FILE'
- X/*
- X * built-in Bourne commands
- X */
- X
- X#ifndef lint
- Xstatic char *RCSid = "Id: /u/egisin/sh/src/RCS/c_sh.c,v 3.1 88/11/03 09:14:31 egisin Exp $";
- Xstatic char *sccs_id = "@(#)c_sh.c 1.3 91/11/09 15:35:24 (sjg)";
- X#endif
- X
- X#include <stddef.h>
- X#include <stdio.h>
- X#include <string.h>
- X#include <errno.h>
- X#include <signal.h>
- X#include <setjmp.h>
- X#include <sys/times.h>
- X#include <unistd.h> /* getcwd */
- X#include "sh.h"
- X#include "lex.h"
- X#include "tree.h"
- X#include "table.h"
- X
- Xstatic char *clocktos();
- X
- Xint
- Xc_label(wp)
- X char **wp;
- X{
- X return 0;
- X}
- X
- Xint
- Xc_shift(wp)
- X register char **wp;
- X{
- X register struct block *l = e.loc;
- X register int n;
- X
- X n = wp[1] ? evaluate(wp[1]) : 1;
- X if (l->argc < n) {
- X errorf("nothing to shift\n");
- X return (1);
- X }
- X l->argv[n] = l->argv[0];
- X l->argv += n;
- X l->argc -= n;
- X return 0;
- X}
- X
- Xint
- Xc_umask(wp)
- X register char **wp;
- X{
- X register int i;
- X register char *cp;
- X
- X if ((cp = wp[1]) == NULL) {
- X i = umask(0);
- X umask(i);
- X printf("%#3.3o\n", i); /* should this be shell output? */
- X } else {
- X for (i = 0; *cp>='0' && *cp<='7'; cp++)
- X i = i*8 + (*cp-'0');
- X umask(i);
- X }
- X return 0;
- X}
- X
- Xint
- Xc_dot(wp)
- X char **wp;
- X{
- X char *file, *cp;
- X
- X if ((cp = wp[1]) == NULL)
- X return 0;
- X file = search(cp, path, 0);
- X if (file == NULL)
- X errorf("%s: not found\n", cp);
- X if (include(file))
- X return exstat;
- X return -1;
- X}
- X
- Xint
- Xc_wait(wp)
- X char **wp;
- X{
- X register char *cp;
- X
- X wp++;
- X cp = *wp;
- X if (cp == NULL) cp = "%";
- X /* todo: print status ? */
- X return waitfor(j_lookup(cp));
- X}
- X
- Xint
- Xc_read(wp)
- X register char **wp;
- X{
- X register int c = 0;
- X FILE *f = stdin;
- X int expand = 1;
- X register char *cp;
- X
- X for (wp++; (cp = *wp) != NULL && *cp++ == '-'; wp++) {
- X while (*cp) switch (*cp++) {
- X case 'e':
- X expand = 1;
- X break;
- X case 'r':
- X expand = 0;
- X break;
- X case 'u':
- X if (!digit(*cp) || (f = shf[*cp++-'0']) == NULL)
- X errorf("bad -u argument\n");
- X break;
- X }
- X }
- X
- X if (*wp == NULL)
- X errorf("missing name\n");
- X if ((cp = strchr(*wp, '?')) != NULL) {
- X *cp = 0;
- X if (flag[FTALKING]) {
- X shellf("%s ", cp+1);
- X fflush(shlout);
- X }
- X }
- X
- X for (; *wp != NULL; wp++) {
- X for (cp = line; cp <= line+LINE; ) {
- X if (c == '\n')
- X break;
- X c = getc(f);
- X if (c == EOF)
- X return 1;
- X if (expand && c == '\\') {
- X c = getc(f);
- X if (c == '\n')
- X c = 0;
- X else
- X *cp++ = c;
- X continue;
- X }
- X if (c == '\n' || wp[1] && ctype(c, C_IFS))
- X break;
- X *cp++ = c;
- X }
- X *cp = 0;
- X setstr(global(*wp), line);
- X }
- X return 0;
- X}
- X
- Xint
- Xc_eval(wp)
- X register char **wp;
- X{
- X register struct source *s;
- X
- X s = pushs(SWORDS);
- X s->u.strv = wp+1;
- X return shell(s);
- X}
- X
- Xvoid setsig ARGS((struct trap *p, handler_t f));
- X
- Xint
- Xc_trap(wp)
- X register char **wp;
- X{
- X int i;
- X char *s;
- X register struct trap *p;
- X
- X wp++;
- X if (*wp == NULL) {
- X for (p = sigtraps, i = SIGNALS; --i >= 0; p++) {
- X if (p->trap != NULL)
- X shellf("%s: %s\n", p->name, p->trap);
- X }
- X return 0;
- X }
- X
- X s = (gettrap(*wp) == NULL) ? *wp++ : NULL; /* get command */
- X if (s != NULL && s[0] == '-' && s[1] == '\0')
- X s = NULL;
- X
- X /* set/clear traps */
- X while (*wp != NULL) {
- X p = gettrap(*wp++);
- X if (p == NULL)
- X errorf("trap: bad signal %s\n", wp[-1]);
- X if (p->trap != NULL)
- X afree((Void*)p->trap, APERM);
- X p->trap = NULL;
- X if (s != NULL) {
- X if (strlen(s) != 0) {
- X p->trap = strsave(s, APERM);
- X setsig(p, trapsig);
- X } else
- X setsig(p, (handler_t)SIG_IGN);
- X } else
- X /* todo: restore to orginal value */
- X setsig(p,
- X (p->signal==SIGINT || p->signal==SIGQUIT) && flag[FTALKING]
- X ? (handler_t)SIG_IGN : (handler_t)SIG_DFL);
- X }
- X return 0;
- X}
- X
- Xvoid
- Xsetsig(p, f)
- X register struct trap *p;
- X void (*f)();
- X{
- X if (p->signal == 0)
- X return;
- X if (signal(p->signal, SIG_IGN) != SIG_IGN || p->ourtrap) {
- X p->ourtrap = 1;
- X signal(p->signal, f);
- X }
- X}
- X
- Xint
- Xc_return(wp)
- X char **wp;
- X{
- X wp++;
- X if (*wp != NULL)
- X exstat = getn(*wp);
- X quitenv(); /* pop E_TCOM */
- X while (e.type == E_LOOP || e.type == E_EXEC)
- X quitenv();
- X if (e.type == E_FUNC)
- X longjmp(e.jbuf, 1);
- X leave(exstat);
- X}
- X
- Xint
- Xc_brkcont(wp)
- X register char **wp;
- X{
- X int quit;
- X
- X quit = wp[1] == NULL ? 1 : getn(wp[1]);
- X quitenv(); /* pop E_TCOM */
- X while (e.type == E_LOOP || e.type == E_EXEC) {
- X if (e.type == E_LOOP && --quit <= 0)
- X longjmp(e.jbuf, (*wp[0] == 'b') ? LBREAK : LCONTIN);
- X quitenv();
- X }
- X errorf("cannot %s\n", wp[0]);
- X}
- X
- X
- X/* 91-05-27 <sjg>
- X * we are supposed to not exit first try
- X * if there are stopped jobs.
- X */
- Xint
- Xc_exit(wp)
- X char **wp;
- X{
- X register char *cp;
- X static int extry = 0;
- X
- X#ifdef JOBS
- X if (extry++ == 0)
- X {
- X if (flag[FMONITOR] && j_stopped()) /* todo: only once */
- X {
- X errorf("There are stopped jobs\n");
- X return 1;
- X }
- X }
- X#endif
- X e.oenv = NULL;
- X if ((cp = wp[1]) != NULL)
- X exstat = getn(cp);
- X leave(exstat);
- X}
- X
- Xint
- Xc_set(wp)
- X register char **wp;
- X{
- X struct block *l = e.loc;
- X register struct tbl *vp, **p;
- X register char **owp = wp;
- X register char *cp;
- X int old_fmonitor = flag[FMONITOR];
- X
- X if ((cp = *++wp) == NULL) {
- X static char * Const args [] = {"set", "-", NULL};
- X extern int c_typeset ARGS((char **args));
- X return c_typeset(args);
- X }
- X
- X for (; (cp = *wp) != NULL && (*cp == '-' || *cp == '+');) {
- X int i, n = *cp++ == '-'; /* set or clear flag */
- X wp++;
- X if (*cp == '\0') {
- X if (n)
- X flag[FXTRACE] = flag[FVERBOSE] = 0;
- X break;
- X }
- X if (*cp == '-')
- X goto setargs;
- X for (; *cp != '\0'; cp++)
- X if (*cp == 'o') {
- X if (*wp == NULL) {
- X printoptions();
- X return 0;
- X }
- X i = option(*wp++);
- X if (i == 0)
- X shellf("%s: unknown option\n", *--wp);
- X flag[i] = n;
- X if (i == FEMACS && n)
- X flag[FVI] = 0;
- X else if (i == FVI && n)
- X flag[FEMACS] = 0;
- X } else if (*cp>='a' && *cp<='z')
- X flag[FLAG(*cp)] = n;
- X else
- X errorf("%c: bad flag\n", *cp);
- X if (flag[FTALKING])
- X flag[FERREXIT] = 0;
- X }
- X
- X#ifdef JOBS
- X if (old_fmonitor != flag[FMONITOR])
- X j_change();
- X#endif
- X
- X /* set $# and $* */
- X if (*wp != NULL) {
- X setargs:
- X owp = --wp;
- X wp[0] = l->argv[0]; /* save $0 */
- X while (*++wp != NULL)
- X *wp = strsave(*wp, &l->area);
- X l->argc = wp - owp - 1;
- X l->argv = (char **) alloc(sizeofN(char *, l->argc+2), &l->area);
- X for (wp = l->argv; (*wp++ = *owp++) != NULL; )
- X ;
- X resetopts();
- X }
- X return 0;
- X}
- X
- Xint
- Xc_unset(wp)
- X register char **wp;
- X{
- X register char *id;
- X int flagf = 0;
- X
- X for (wp++; (id = *wp) != NULL && *id == '-'; wp++)
- X if (*++id == 'f')
- X flagf++;
- X for (; (id = *wp) != NULL; wp++)
- X if (!flagf) { /* unset variable */
- X unset(global(id));
- X } else { /* unset function */
- X define(id, (struct op *)NULL);
- X }
- X return 0;
- X}
- X
- Xint
- Xc_ulimit(wp)
- X register char **wp;
- X{
- X extern int do_ulimit();
- X
- X return do_ulimit(wp[1], wp[2]);
- X}
- X
- Xint
- Xc_times(wp)
- X char **wp;
- X{
- X struct tms all;
- X
- X (void) times(&all);
- X printf("Shell: ");
- X printf("%8s user ", clocktos(all.tms_utime));
- X printf("%8s system\n", clocktos(all.tms_stime));
- X printf("Kids: ");
- X printf("%8s user ", clocktos(all.tms_cutime));
- X printf("%8s system\n", clocktos(all.tms_cstime));
- X
- X return 0;
- X}
- X
- X/*
- X * time pipeline (really a statement, not a built-in comman)
- X */
- Xint
- Xtimex(t, f)
- X struct op *t;
- X int f;
- X{
- X int rv;
- X struct tms t0, t1;
- X clock_t t0t, t1t;
- X extern clock_t j_utime, j_stime; /* computed by j_wait */
- X
- X j_utime = j_stime = 0;
- X t0t = times(&t0);
- X rv = execute(t->left, f);
- X t1t = times(&t1);
- X
- X shellf("%8s real ", clocktos(t1t - t0t));
- X shellf("%8s user ",
- X clocktos(t1.tms_utime - t0.tms_utime + j_utime));
- X shellf("%8s system ",
- X clocktos(t1.tms_stime - t0.tms_stime + j_stime));
- X shellf("\n");
- X
- X return rv;
- X}
- X
- Xstatic char *
- Xclocktos(t)
- X clock_t t;
- X{
- X static char temp[20];
- X register int i;
- X register char *cp = temp + sizeof(temp);
- X
- X#if CLK_TCK != 100 /* convert to 1/100'ths */
- X t = (t < 1000000000/CLK_TCK) ?
- X (t * 100) / CLK_TCK : (t / CLK_TCK) * 100;
- X#endif
- X
- X *--cp = '\0';
- X *--cp = 's';
- X for (i = -2; i <= 0 || t > 0; i++) {
- X if (i == 0)
- X *--cp = '.';
- X *--cp = '0' + (char)(t%10);
- X t /= 10;
- X }
- X return cp;
- X}
- X
- X/* dummy function, special case in comexec() */
- Xint
- Xc_exec(wp)
- X char ** wp;
- X{
- X return 0;
- X}
- X
- X/* dummy function, special case in comexec() */
- Xint
- Xc_builtin(wp)
- X char ** wp;
- X{
- X return 0;
- X}
- X
- Xextern int c_test(); /* in test.c */
- X
- XConst struct builtin shbuiltins [] = {
- X {"=:", c_label},
- X {"=.", c_dot},
- X {"[", c_test},
- X {"=builtin", c_builtin},
- X {"=exec", c_exec},
- X {"=shift", c_shift},
- X {"=wait", c_wait},
- X {"read", c_read},
- X {"=eval", c_eval},
- X {"=trap", c_trap},
- X {"=break", c_brkcont},
- X {"=continue", c_brkcont},
- X {"=exit", c_exit},
- X {"=return", c_return},
- X {"=set", c_set},
- X {"unset", c_unset},
- X {"umask", c_umask},
- X {"test", c_test},
- X {"=times", c_times},
- X {"ulimit", c_ulimit},
- X {NULL, NULL}
- X};
- X
- END_OF_FILE
- if test 8560 -ne `wc -c <'sh/c_sh.c'`; then
- echo shar: \"'sh/c_sh.c'\" unpacked with wrong size!
- fi
- # end of 'sh/c_sh.c'
- fi
- if test -f 'sh/c_test.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sh/c_test.c'\"
- else
- echo shar: Extracting \"'sh/c_test.c'\" \(7284 characters\)
- sed "s/^X//" >'sh/c_test.c' <<'END_OF_FILE'
- X/*
- X * test(1); version 7-like -- author Erik Baalbergen
- X * modified by Eric Gisin to be used as built-in.
- X * modified by Arnold Robbins to add SVR3 compatibility
- X * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket).
- X */
- X
- Xstatic char *RCSid = "$Id: c_test.c,v 3.3 89/03/27 15:47:25 egisin Exp $";
- X
- X#include <stddef.h>
- X#include <string.h>
- X#include <signal.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include "sh.h"
- X
- X/* test(1) accepts the following grammar:
- X oexpr ::= aexpr | aexpr "-o" oexpr ;
- X aexpr ::= nexpr | nexpr "-a" aexpr ;
- X nexpr ::= primary ! "!" primary
- X primary ::= unary-operator operand
- X | operand binary-operator operand
- X | operand
- X | "(" oexpr ")"
- X ;
- X unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"|
- X "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S";
- X
- X binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"|
- X "-nt"|"-ot"|"-ef";
- X operand ::= <any legal UNIX file name>
- X*/
- X
- X#define EOI 0
- X#define FILRD 1
- X#define FILWR 2
- X#define FILREG 3
- X#define FILID 4
- X#define FILGZ 5
- X#define FILTT 6
- X#define STZER 7
- X#define STNZE 8
- X#define STEQL 9
- X#define STNEQ 10
- X#define INTEQ 11
- X#define INTNE 12
- X#define INTGE 13
- X#define INTGT 14
- X#define INTLE 15
- X#define INTLT 16
- X#define UNOT 17
- X#define BAND 18
- X#define BOR 19
- X#define LPAREN 20
- X#define RPAREN 21
- X#define OPERAND 22
- X#define FILEX 23
- X#define FILCDEV 24
- X#define FILBDEV 25
- X#define FILFIFO 26
- X#define FILSETU 27
- X#define FILSETG 28
- X#define FILSTCK 29
- X#define FILSYM 30
- X#define FILNT 31
- X#define FILOT 32
- X#define FILEQ 33
- X#define FILSOCK 34
- X#define FILUID 35
- X#define FILGID 36
- X#define OPTION 37
- X
- X#define UNOP 1
- X#define BINOP 2
- X#define BUNOP 3
- X#define BBINOP 4
- X#define PAREN 5
- X
- Xstruct t_op {
- X char *op_text;
- X short op_num, op_type;
- X} Const ops [] = {
- X {"-r", FILRD, UNOP},
- X {"-w", FILWR, UNOP},
- X {"-x", FILEX, UNOP},
- X {"-f", FILREG, UNOP},
- X {"-d", FILID, UNOP},
- X {"-c", FILCDEV,UNOP},
- X {"-b", FILBDEV,UNOP},
- X {"-p", FILFIFO,UNOP},
- X {"-u", FILSETU,UNOP},
- X {"-g", FILSETG,UNOP},
- X {"-k", FILSTCK,UNOP},
- X {"-s", FILGZ, UNOP},
- X {"-t", FILTT, UNOP},
- X {"-z", STZER, UNOP},
- X {"-n", STNZE, UNOP},
- X#if 0 /* conficts with binary -o */
- X {"-o", OPTION, UNOP},
- X#endif
- X {"-U", FILUID, UNOP},
- X {"-G", FILGID, UNOP},
- X {"-L", FILSYM, UNOP},
- X {"-S", FILSOCK,UNOP},
- X {"=", STEQL, BINOP},
- X {"!=", STNEQ, BINOP},
- X {"-eq", INTEQ, BINOP},
- X {"-ne", INTNE, BINOP},
- X {"-ge", INTGE, BINOP},
- X {"-gt", INTGT, BINOP},
- X {"-le", INTLE, BINOP},
- X {"-lt", INTLT, BINOP},
- X {"-nt", FILNT, BINOP},
- X {"-ot", FILOT, BINOP},
- X {"-ef", FILEQ, BINOP},
- X {"!", UNOT, BUNOP},
- X {"-a", BAND, BBINOP},
- X {"-o", BOR, BBINOP},
- X {"(", LPAREN, PAREN},
- X {")", RPAREN, PAREN},
- X {0, 0, 0}
- X};
- X
- Xchar **t_wp;
- Xstruct t_op Const *t_wp_op;
- X
- Xstatic void syntax();
- X
- Xint
- Xc_test(wp)
- X char **wp;
- X{
- X int res;
- X
- X t_wp = wp+1;
- X if (strcmp(wp[0], "[") == 0) {
- X while (*wp != NULL)
- X wp++;
- X if (strcmp(*--wp, "]") != 0)
- X errorf("[: missing ]\n");
- X *wp = NULL;
- X }
- X res = *t_wp == NULL || !oexpr(t_lex(*t_wp));
- X
- X if (*t_wp != NULL && *++t_wp != NULL)
- X syntax(*t_wp, "unknown operand");
- X
- X return res;
- X}
- X
- Xstatic void
- Xsyntax(op, msg)
- X char *op;
- X char *msg;
- X{
- X if (op && *op)
- X errorf("test: %s: %s\n", op, msg);
- X else
- X errorf("test: %s\n", msg);
- X}
- X
- Xoexpr(n)
- X{
- X int res;
- X
- X res = aexpr(n);
- X if (t_lex(*++t_wp) == BOR)
- X return oexpr(t_lex(*++t_wp)) || res;
- X t_wp--;
- X return res;
- X}
- X
- Xaexpr(n)
- X{
- X int res;
- X
- X res = nexpr(n);
- X if (t_lex(*++t_wp) == BAND)
- X return aexpr(t_lex(*++t_wp)) && res;
- X t_wp--;
- X return res;
- X}
- X
- Xnexpr(n)
- X int n; /* token */
- X{
- X if (n == UNOT)
- X return !nexpr(t_lex(*++t_wp));
- X return primary(n);
- X}
- X
- Xprimary(n)
- X int n; /* token */
- X{
- X register char *opnd1, *opnd2;
- X int res;
- X
- X if (n == EOI)
- X syntax(NULL, "argument expected");
- X if (n == LPAREN) {
- X res = oexpr(t_lex(*++t_wp));
- X if (t_lex(*++t_wp) != RPAREN)
- X syntax(NULL, "closing paren expected");
- X return res;
- X }
- X if (t_wp_op && t_wp_op->op_type == UNOP) {
- X /* unary expression */
- X if (*++t_wp == NULL && n != FILTT)
- X syntax(t_wp_op->op_text, "argument expected");
- X switch (n) {
- X case OPTION:
- X return flag[option(*t_wp)];
- X case STZER:
- X return strlen(*t_wp) == 0;
- X case STNZE:
- X return strlen(*t_wp) != 0;
- X case FILTT:
- X if (!digit(**t_wp))
- X return filstat("0", n);
- X default: /* all other FIL* */
- X return filstat(*t_wp, n);
- X }
- X }
- X opnd1 = *t_wp;
- X (void) t_lex(*++t_wp);
- X if (t_wp_op && t_wp_op->op_type == BINOP) {
- X struct t_op Const *op = t_wp_op;
- X
- X if ((opnd2 = *++t_wp) == (char *)0)
- X syntax(op->op_text, "argument expected");
- X
- X switch (op->op_num) {
- X case STEQL:
- X return strcmp(opnd1, opnd2) == 0;
- X case STNEQ:
- X return strcmp(opnd1, opnd2) != 0;
- X case INTEQ:
- X return evaluate(opnd1) == evaluate(opnd2);
- X case INTNE:
- X return evaluate(opnd1) != evaluate(opnd2);
- X case INTGE:
- X return evaluate(opnd1) >= evaluate(opnd2);
- X case INTGT:
- X return evaluate(opnd1) > evaluate(opnd2);
- X case INTLE:
- X return evaluate(opnd1) <= evaluate(opnd2);
- X case INTLT:
- X return evaluate(opnd1) < evaluate(opnd2);
- X case FILNT:
- X return newerf (opnd1, opnd2);
- X case FILOT:
- X return olderf (opnd1, opnd2);
- X case FILEQ:
- X return equalf (opnd1, opnd2);
- X }
- X }
- X t_wp--;
- X return strlen(opnd1) > 0;
- X}
- X
- Xfilstat(nm, mode)
- X char *nm;
- X{
- X struct stat s;
- X
- X switch (mode) {
- X case FILRD:
- X return eaccess(nm, 4) == 0;
- X case FILWR:
- X return eaccess(nm, 2) == 0;
- X case FILEX:
- X return eaccess(nm, 1) == 0;
- X case FILREG:
- X return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFREG;
- X case FILID:
- X return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFDIR;
- X case FILCDEV:
- X return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFCHR;
- X case FILBDEV:
- X return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFBLK;
- X case FILFIFO:
- X#ifdef S_IFIFO
- X return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFIFO;
- X#else
- X return 0;
- X#endif
- X case FILSETU:
- X return stat(nm, &s) == 0 && (s.st_mode & S_ISUID) == S_ISUID;
- X case FILSETG:
- X return stat(nm, &s) == 0 && (s.st_mode & S_ISGID) == S_ISGID;
- X case FILSTCK:
- X return stat(nm, &s) == 0 && (s.st_mode & S_ISVTX) == S_ISVTX;
- X case FILGZ:
- X return stat(nm, &s) == 0 && s.st_size > 0L;
- X case FILTT:
- X return isatty(getn(nm));
- X case FILUID:
- X return stat(nm, &s) == 0 && s.st_uid == geteuid();
- X case FILGID:
- X return stat(nm, &s) == 0 && s.st_gid == getegid();
- X#ifdef S_IFLNK
- X case FILSYM:
- X return lstat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFLNK;
- X#endif
- X#ifdef S_IFSOCK
- X case FILSOCK:
- X return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFSOCK;
- X#endif
- X default:
- X return 1;
- X }
- X}
- X
- Xint
- Xt_lex(s)
- X register char *s;
- X{
- X register struct t_op Const *op = ops;
- X
- X if (s == 0) {
- X t_wp_op = (struct t_op *)0;
- X return EOI;
- X }
- X while (op->op_text) {
- X if (strcmp(s, op->op_text) == 0) {
- X t_wp_op = op;
- X return op->op_num;
- X }
- X op++;
- X }
- X t_wp_op = (struct t_op *)0;
- X return OPERAND;
- X}
- X
- Xnewerf (f1, f2)
- Xchar *f1, *f2;
- X{
- X struct stat b1, b2;
- X
- X return (stat (f1, &b1) == 0 &&
- X stat (f2, &b2) == 0 &&
- X b1.st_mtime > b2.st_mtime);
- X}
- X
- Xolderf (f1, f2)
- Xchar *f1, *f2;
- X{
- X struct stat b1, b2;
- X
- X return (stat (f1, &b1) == 0 &&
- X stat (f2, &b2) == 0 &&
- X b1.st_mtime < b2.st_mtime);
- X}
- X
- Xequalf (f1, f2)
- Xchar *f1, *f2;
- X{
- X struct stat b1, b2;
- X
- X return (stat (f1, &b1) == 0 &&
- X stat (f2, &b2) == 0 &&
- X b1.st_dev == b2.st_dev &&
- X b1.st_ino == b2.st_ino);
- X}
- X
- END_OF_FILE
- if test 7284 -ne `wc -c <'sh/c_test.c'`; then
- echo shar: \"'sh/c_test.c'\" unpacked with wrong size!
- fi
- # end of 'sh/c_test.c'
- fi
- if test -f 'sh/edit.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sh/edit.c'\"
- else
- echo shar: Extracting \"'sh/edit.c'\" \(7903 characters\)
- sed "s/^X//" >'sh/edit.c' <<'END_OF_FILE'
- X/*
- X * Command line editing - common code
- X */
- X
- X#include "config.h"
- X#if defined(EMACS) || defined(VI)
- X
- X#ifndef lint
- Xstatic char *RCSid = "$Id: edit.c,v 3.2 89/03/27 15:47:34 egisin Exp $";
- Xstatic char *sccs_id = "@(#)edit.c 1.4 91/11/09 15:35:07 (sjg)";
- X#endif
- X
- X#include <stddef.h>
- X#include <stdlib.h>
- X#include <string.h>
- X#include <stdio.h>
- X#include <unistd.h>
- X#include <signal.h>
- X#include <fcntl.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include "sh.h"
- X#include "lex.h"
- X#include "tty.h"
- X#define EXTERN
- X#include "edit.h"
- X#undef EXTERN
- X
- X#ifdef _CRAY2
- Xextern unsigned sleep();
- X#endif
- X
- X#if 0
- Xint x_do_init = 1; /* set up tty modes */
- Xint x_cols = 80; /* todo: $COLUMNS */
- Xint ed_erase = -1, ed_kill = -1, ed_werase = -1, ed_intr = -1, ed_quit = -1;
- X#endif
- X
- Xstatic int x_noecho = 0;
- X
- X/*
- X * read an edited command line
- X */
- Xint
- Xx_read(fd, buf, len)
- X int fd; /* not used */
- X char *buf;
- X size_t len;
- X{
- X static int setup_done = 0;
- X char c;
- X int i;
- X
- X if (setup_done != 42)
- X {
- X setup_done = 42; /* these get done once only */
- X x_do_init = 1;
- X x_cols = 80;
- X x_col = 0;
- X ed_erase = -1, ed_kill = -1, ed_werase = -1, ed_intr = -1, ed_quit = -1;
- X x_adj_ok = 1;
- X x_adj_done = 0;
- X }
- X if (x_do_init)
- X x_init();
- X
- X if (x_noecho)
- X return(read(ttyfd, buf, len));
- X
- X (void)x_mode(TRUE);
- X#ifdef EMACS
- X if (flag[FEMACS])
- X i = x_emacs(buf, len);
- X else
- X#endif
- X#ifdef VI
- X if (flag[FVI])
- X i = x_vi(buf, len);
- X else
- X#endif
- X i = -1; /* internal error */
- X (void) x_mode(FALSE);
- X /* XXX -- doesn't get them all */
- X if (i > 4 && strncmp(buf, "stty", 4) == 0)
- X x_do_init = 1;
- X if (i < 0 && errno == EINTR)
- X trapsig(SIGINT);
- X return i;
- X}
- X
- X/* tty I/O */
- X
- Xint
- Xx_getc()
- X{
- X char c;
- X
- X if (read(ttyfd, &c, 1) != 1)
- X return -1;
- X return c & 0x7F;
- X}
- X
- Xvoid
- Xx_flush()
- X{
- X fflush(stdout);
- X}
- X
- X
- X/* NAME:
- X * x_adjust - redraw the line adjusting starting point etc.
- X *
- X * DESCRIPTION:
- X * This function is called when we have exceeded the bounds
- X * of the edit window. It increments x_adj_done so that
- X * functions like x_ins and x_delete know that we have been
- X * called and can skip the x_bs() stuff which has already
- X * been done by x_redraw.
- X *
- X * RETURN VALUE:
- X * None
- X */
- X
- Xvoid
- Xx_adjust()
- X{
- X x_adj_done++; /* flag the fact that we were called. */
- X /*
- X * we had a promblem if the prompt length > x_cols / 2
- X */
- X if ((xbp = xcp - (x_displen / 2)) < xbuf)
- X xbp = xbuf;
- X xlp_valid = FALSE;
- X x_redraw(x_cols);
- X x_flush();
- X}
- X
- Xvoid
- Xx_putc(c)
- X int c;
- X{
- X if (c == '\r' || c == '\n')
- X x_col = 0;
- X if (x_col < x_cols)
- X {
- X putc(c, stdout);
- X switch(c)
- X {
- X case BEL:
- X break;
- X case '\r':
- X case '\n':
- X break;
- X case '\b':
- X x_col--;
- X break;
- X default:
- X x_col++;
- X break;
- X }
- X }
- X if (x_adj_ok && (x_col < 0 || x_col >= (x_cols - 2)))
- X {
- X x_adjust();
- X }
- X}
- X
- X#ifdef DEBUG
- Xint
- Xx_debug_info()
- X{
- X x_flush();
- X printf("\nksh debug:\n");
- X printf("\tx_col == %d,\t\tx_cols == %d,\tx_displen == %d\n",
- X x_col, x_cols, x_displen);
- X printf("\txcp == 0x%lx,\txep == 0x%lx\n", (long) xcp, (long) xep);
- X printf("\txbp == 0x%lx,\txbuf == 0x%lx\n", (long) xbp, (long) xbuf);
- X printf("\txlp == 0x%lx\n", (long) xlp);
- X printf("\txlp == 0x%lx\n", (long) x_lastcp());
- X printf("\n");
- X x_redraw(-1);
- X return 0;
- X}
- X#endif
- X
- Xvoid
- Xx_puts(s)
- X register char *s;
- X{
- X register int adj = x_adj_done;
- X
- X while (*s && adj == x_adj_done)
- X x_putc(*s++);
- X}
- X
- X#ifdef _BSD
- Xstatic struct sgttyb cb, cborig;
- X#ifdef TIOCGATC
- Xstatic struct ttychars lchars, lcharsorig;
- X#else
- Xstatic struct tchars tchars, tcharsorig;
- Xstatic struct ltchars ltchars, ltcharsorig;
- X#endif
- X#else
- Xstatic struct termio cb, cborig;
- X#endif
- X
- X/* initialize editing mode */
- Xvoid
- Xx_init()
- X{
- X x_do_init = 0;
- X#ifdef _BSD
- X (void)ioctl(ttyfd, TIOCGETP, &cborig);
- X if ((cborig.sg_flags & ECHO) == 0)
- X x_noecho = 1;
- X cb = cborig;
- X ed_erase = cb.sg_erase;
- X ed_kill = cb.sg_kill;
- X cb.sg_flags &= ~ECHO;
- X cb.sg_flags |= CBREAK;
- X#ifdef TIOCGATC
- X (void)ioctl(ttyfd, TIOCGATC, &lcharsorig);
- X lchars = lcharsorig;
- X ed_werase = lchars.tc_werasc;
- X lchars.tc_suspc = -1;
- X lchars.tc_dsuspc = -1;
- X lchars.tc_lnextc = -1;
- X lchars.tc_statc = -1;
- X lchars.tc_intrc = -1;
- X lchars.tc_quitc = -1;
- X lchars.tc_rprntc = -1;
- X#else
- X (void)ioctl(ttyfd, TIOCGETC, &tcharsorig);
- X (void)ioctl(ttyfd, TIOCGLTC, <charsorig);
- X tchars = tcharsorig;
- X ltchars = ltcharsorig;
- X ed_werase = ltchars.t_werasc;
- X ltchars = ltcharsorig;
- X ltchars.t_suspc = -1;
- X ltchars.t_dsuspc = -1;
- X ltchars.t_lnextc = -1;
- X tchars.t_intrc = -1;
- X tchars.t_quitc = -1;
- X ltchars.t_rprntc = -1;
- X#endif
- X#else /* !_BSD */
- X (void)ioctl(ttyfd, TCGETA, &cborig);
- X if ((cborig.c_lflag & ECHO) == 0)
- X x_noecho = 1;
- X cb = cborig;
- X ed_erase = cb.c_cc[VERASE]; /* TODO */
- X ed_kill = cb.c_cc[VKILL]; /* TODO */
- X ed_intr = cb.c_cc[VINTR];
- X ed_quit = cb.c_cc[VQUIT];
- X#ifdef _CRAY2 /* brain-damaged terminal handler */
- X cb.c_lflag &= ~(ICANON|ECHO);
- X /* rely on print routine to map '\n' to CR,LF */
- X#else
- X cb.c_iflag &= ~(INLCR|ICRNL);
- X#ifdef _BSD_SYSV /* need to force CBREAK instead of RAW (need CRMOD on output) */
- X cb.c_lflag &= ~(ICANON|ECHO);
- X#else
- X#ifdef SWTCH /* need CBREAK to handle swtch char */
- X cb.c_lflag &= ~(ICANON|ECHO);
- X cb.c_lflag |= ISIG;
- X cb.c_cc[VINTR] = 0377;
- X cb.c_cc[VQUIT] = 0377;
- X#else
- X cb.c_lflag &= ~(ISIG|ICANON|ECHO);
- X#endif
- X#endif
- X cb.c_cc[VTIME] = 0;
- X cb.c_cc[VMIN] = 1;
- X#endif /* _CRAY2 */
- X#endif
- X#ifdef EMACS
- X x_emacs_keys(ed_erase, ed_kill, ed_werase, ed_intr, ed_quit);
- X#endif
- X}
- X
- Xstatic bool_t x_cur_mode = FALSE;
- X
- X/* set/clear tty cbreak mode */
- X
- X#ifdef _BSD
- Xbool_t
- Xx_mode(onoff)
- X bool_t onoff;
- X{
- X bool_t prev;
- X
- X if (x_cur_mode == onoff) return x_cur_mode;
- X prev = x_cur_mode;
- X x_cur_mode = onoff;
- X if (onoff) {
- X (void)ioctl(ttyfd, TIOCSETN, &cb);
- X#ifdef TIOCGATC
- X (void)ioctl(ttyfd, TIOCSATC, &lchars);
- X#else
- X (void)ioctl(ttyfd, TIOCSETC, &tchars);
- X (void)ioctl(ttyfd, TIOCSLTC, <chars);
- X#endif
- X }
- X else {
- X (void)ioctl(ttyfd, TIOCSETN, &cborig);
- X#ifdef TIOCGATC
- X (void)ioctl(ttyfd, TIOCSATC, &lcharsorig);
- X#else
- X (void)ioctl(ttyfd, TIOCSETC, &tcharsorig);
- X (void)ioctl(ttyfd, TIOCSLTC, <charsorig);
- X#endif
- X }
- X return prev;
- X}
- X
- X#else /* !_BSD */
- X
- Xbool_t
- Xx_mode(onoff)
- Xbool_t onoff;
- X{
- X bool_t prev;
- X
- X if (x_cur_mode == onoff) return x_cur_mode;
- X prev = x_cur_mode;
- X x_cur_mode = onoff;
- X
- X if (onoff) {
- X#ifndef TCSETAW /* e.g. Cray-2 */
- X /* first wait for output to drain */
- X#ifdef TCSBRK
- X (void)ioctl(ttyfd, TCSBRK, 1);
- X#else /* the following kludge is minimally intrusive, but sometimes fails */
- X (void)sleep((unsigned)1); /* fake it */
- X#endif
- X#endif
- X#if defined(_BSD_SYSV) || !defined(TCSETAW)
- X/* _BSD_SYSV needs to force TIOCSETN instead of TIOCSETP (preserve type-ahead) */
- X (void)ioctl(ttyfd, TCSETA, &cb);
- X#else
- X (void)ioctl(ttyfd, TCSETAW, &cb);
- X#endif
- X }
- X else {
- X#ifndef TCSETAW /* e.g. Cray-2 */
- X /* first wait for output to drain */
- X#ifdef TCSBRK
- X (void)ioctl(ttyfd, TCSBRK, 1);
- X#else
- X/* doesn't seem to be necessary when leaving xmode */
- X/* (void)sleep((unsigned)1); /* fake it */
- X#endif
- X#endif
- X#if defined(_BSD_SYSV) || !defined(TCSETAW)
- X/* _BSD_SYSV needs to force TIOCSETN instead of TIOCSETP (preserve type-ahead) */
- X (void)ioctl(ttyfd, TCSETA, &cborig);
- X#else
- X (void)ioctl(ttyfd, TCSETAW, &cborig);
- X#endif
- X }
- X return prev;
- X}
- X#endif /* _BSD */
- X
- X
- X/* NAME:
- X * promptlen - calculate the length of PS1 etc.
- X *
- X * DESCRIPTION:
- X * This function is based on a fix from guy@demon.co.uk
- X * It fixes a bug in that if PS1 contains '!', the length
- X * given by strlen() is probably wrong.
- X *
- X * RETURN VALUE:
- X * length
- X */
- X
- Xint
- Xpromptlen(cp)
- X register char *cp;
- X{
- X register int count = 0;
- X
- X while (*cp)
- X {
- X if ( *cp++ != '!' )
- X count++;
- X else
- X if ( *cp == '!' )
- X {
- X cp++;
- X count++;
- X }
- X else
- X {
- X register int i = source->line;
- X
- X do
- X {
- X count ++;
- X }
- X while( ( i /= 10 ) > 0 );
- X }
- X }
- X return count;
- X}
- X
- X#endif
- END_OF_FILE
- if test 7903 -ne `wc -c <'sh/edit.c'`; then
- echo shar: \"'sh/edit.c'\" unpacked with wrong size!
- fi
- # end of 'sh/edit.c'
- fi
- if test -f 'sh/history.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sh/history.c'\"
- else
- echo shar: Extracting \"'sh/history.c'\" \(7391 characters\)
- sed "s/^X//" >'sh/history.c' <<'END_OF_FILE'
- X/*
- X * command history
- X *
- X * only implements in-memory history.
- X */
- X
- Xstatic char *RCSid = "$Id: history.c,v 3.3 89/01/27 00:08:27 egisin Exp $";
- X
- X#include <stddef.h>
- X#include <stdio.h>
- X#include <string.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include "sh.h"
- X#include "lex.h"
- X
- Xchar *histrpl();
- Xchar **current;
- Xint curpos;
- X
- Xc_fc(wp)
- X register char **wp;
- X{
- X register char *id;
- X FILE *f;
- X struct temp *tf;
- X register char **hp;
- X char **hbeg, **hend;
- X char *p, *cmd = NULL;
- X int lflag = 0, nflag = 0, sflag = 0, rflag = 0, gflag = 0;
- X int done = 0;
- X void histbackup();
- X
- X for (wp++; (id = *wp) != NULL && *id++ == '-' && !done; wp++)
- X while (*id && !done) {
- X switch (*id++) {
- X case 'l':
- X lflag++;
- X break;
- X case 'n':
- X nflag++;
- X break;
- X case 'r':
- X rflag++;
- X break;
- X case 'g':
- X gflag++;
- X break;
- X case 'e':
- X if (++wp && (p = *wp)) {
- X if (p[0] == '-' && !p[1]) {
- X sflag++;
- X } else {
- X cmd = alloc((size_t)(strlen(p)+4),ATEMP);
- X strcpy(cmd, p);
- X strcat(cmd, " $_");
- X }
- X } else
- X errorf("argument expected\n");
- X id = "";
- X break;
- X default:
- X wp--;
- X done++;
- X break;
- X }
- X }
- X
- X if (sflag) {
- X char *pat = NULL, *rep = NULL;
- X
- X hp = histptr - 1;
- X while ((id = *wp++) != NULL) {
- X /* todo: multiple substitutions */
- X if ((p = strchr(id, '=')) != NULL) {
- X pat = id;
- X rep = p;
- X *rep++ = '\0';
- X } else
- X hp = histget(id);
- X }
- X
- X if (hp == NULL || hp < history)
- X errorf("cannot find history\n");
- X if (pat == NULL)
- X strcpy(line, *hp);
- X else
- X histrpl(*hp, pat, rep, gflag);
- X histbackup();
- X histsave(line);
- X histpush--;
- X line[0] = '\0';
- X return 0;
- X }
- X
- X if (*wp != NULL) {
- X hbeg = histget(*wp++); /* first */
- X if (*wp != NULL)
- X hend = histget(*wp++); /* last */
- X else if (lflag)
- X hend = histptr;
- X else
- X hend = hbeg;
- X } else {
- X if (lflag)
- X hbeg = histptr - 16, hend = histptr;
- X else
- X hbeg = hend = histptr - 1;
- X if (hbeg < history)
- X hbeg = history;
- X }
- X if (hbeg == NULL || hend == NULL)
- X errorf("can't find history\n");
- X
- X if (lflag)
- X f = stdout;
- X else {
- X nflag++;
- X tf = maketemp(ATEMP);
- X tf->next = e.temps; e.temps = tf;
- X f = fopen(tf->name, "w");
- X if (f == NULL)
- X errorf("cannot create temp file %s", tf->name);
- X setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
- X }
- X
- X for (hp = (rflag ? hend : hbeg); rflag ? (hp >= hbeg) : (hp <= hend);
- X rflag ? hp-- : hp++) {
- X if (!nflag)
- X fprintf(f, "%3d: ", source->line - (int)(histptr-hp));
- X fprintf(f, "%s\n", *hp);
- X }
- X
- X if (lflag)
- X return 0;
- X else
- X fclose(f);
- X
- X setstr(local("_"), tf->name);
- X if (cmd) {
- X command(cmd); /* edit temp file */
- X afree(cmd, ATEMP);
- X } else
- X command("${FCEDIT:-/bin/ed} $_");
- X
- X f = fopen(tf->name, "r");
- X if (f == NULL)
- X errorf("cannot open temp file %s\n", tf->name);
- X setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
- X /* we push the editted lines onto the history list */
- X while (fgets(line, sizeof(line), f) != NULL) {
- X histsave(line);
- X histpush--;
- X }
- X line[0] = '\0';
- X fclose(f);
- X
- X return 0;
- X}
- X
- X/******************************/
- X/* Back up over last histsave */
- X/******************************/
- Xvoid
- Xhistbackup()
- X{
- X static int last_line = -1;
- X
- X if (histptr > history && last_line != source->line) {
- X source->line--;
- X afree((Void*)*histptr, APERM);
- X histptr--;
- X last_line = source->line;
- X }
- X}
- X
- X/*
- X * save command in history
- X */
- Xvoid
- Xhistsave(cmd)
- X char *cmd;
- X{
- X register char **hp = histptr;
- X char *cp;
- X
- X if (++hp >= history + HISTORY) { /* remove oldest command */
- X afree((Void*)*history, APERM);
- X for (hp = history; hp < history + HISTORY - 1; hp++)
- X hp[0] = hp[1];
- X }
- X *hp = strsave(cmd, APERM);
- X if ((cp = strchr(*hp, '\n')) != NULL)
- X *cp = '\0';
- X histptr = hp;
- X}
- X
- X/*
- X * get pointer to history given pattern
- X * pattern is a number or string
- X */
- Xchar **
- Xhistget(str)
- X char *str;
- X{
- X register char **hp = NULL;
- X
- X if (*str == '-')
- X hp = histptr + getn(str);
- X else
- X if (digit(*str))
- X hp = histptr + (getn(str) - source->line);
- X else
- X if (*str == '?') { /* unanchored match */
- X for (hp = histptr-1; hp >= history; hp--)
- X if (strstr(*hp, str+1) != NULL)
- X break;
- X } else { /* anchored match */
- X for (hp = histptr; hp >= history; hp--)
- X if (strncmp(*hp, str, strlen(str)) == 0)
- X break;
- X }
- X
- X return (history <= hp && hp <= histptr) ? hp : NULL;
- X}
- X
- Xchar *
- Xhistrpl(s, pat, rep, global)
- X char *s;
- X char *pat, *rep;
- X int global;
- X{
- X char *s1, *p, *last = NULL;
- X int len = strlen(pat);
- X
- X if (strlen(s) - strlen(pat) + strlen(rep) >= LINE)
- X errorf("substitution too long\n");
- X line[0] = '\0';
- X p = line;
- X while (s1 = strstr(s, pat)) {
- X strncpy(p, s, s1 - s); /* first part */
- X strcpy(p + (s1 - s), rep); /* replacement */
- X s = s1 + len;
- X last = s1;
- X p = strchr(p, 0);
- X if (!global)
- X s = "";
- X }
- X if (last)
- X strcpy(p, last + len); /* last part */
- X else
- X errorf("substitution failed\n");
- X return line;
- X}
- X
- X#if 0
- X
- X/* History file management routines (by DPK@BRL) */
- X
- Xvoid
- Xhist_init()
- X{
- X register struct namnod *n;
- X int fd;
- X
- X if (hist_fd >= 0 || (flags&oneflg))
- X return;
- X if ((n = findnam(histname)) == (struct namnod *)0
- X || n->namval == (char *)0)
- X return;
- X if ((fd = open(n->namval, O_RDWR)) >= 0) {
- X hist_load(fd);
- X (void)fcntl(fd, F_SETFL, O_APPEND);
- X }
- X hist_fd = fd;
- X}
- X
- Xvoid
- Xhist_finish()
- X{
- X if (hist_fd >= 0)
- X (void)close(hist_fd);
- X hist_fd = -1;
- X}
- X
- Xvoid
- Xhist_record(buf, len)
- Xchar *buf;
- Xint len;
- X{
- X if (hist_fd >= 0)
- X (void)write(hist_fd, buf, (unsigned)len);
- X}
- X
- Xvoid
- Xhist_load(fd)
- Xint fd;
- X{
- X extern long lseek();
- X struct stat sb;
- X char *x;
- X register char *cmdp, *end;
- X register int len;
- X register int i;
- X
- X if (fstat(fd, &sb) < 0 || sb.st_size <= 0)
- X return;
- X if (x = alloc((unsigned)(sb.st_size+1))) {
- X (void)lseek(fd, 0L, 0);
- X if ((len = read(fd, x, (unsigned)sb.st_size)) <= 0) {
- X free((struct blk *)x);
- X return;
- X }
- X x[len] = 0;
- X end = x;
- X for (;;) {
- X while(*end == NL)
- X end++; /* Skip NL */
- X if (*end == 0)
- X break;
- X cmdp = end;
- X while(*end && *end != NL)
- X end++; /* Goto NL */
- X if (*end == 0)
- X break;
- X if ((len = (end - cmdp)) < 2)
- X continue;
- X if (len >= BUFSIZ)
- X len = BUFSIZ - 1; /* Protection */
- X i = curhist % NHISTORY;
- X if(histbuf[i])
- X free((struct blk *)histbuf[i]);
- X histbuf[i] = alloc((unsigned)(len+1));
- X (void)strncpy(histbuf[i], cmdp, len);
- X histbuf[i][len] = 0;
- X curhist++;
- X histpc=curhist;
- X }
- X free((struct blk *)x);
- X }
- X return;
- X}
- X
- X#endif
- X
- X/*
- X * Return the current position.
- X */
- Xchar **
- Xhistpos()
- X{
- X return current;
- X}
- X
- Xint
- XhistN()
- X{
- X return curpos;
- X}
- X
- Xint
- Xhistnum(n)
- X{
- X int last = histptr - history;
- X
- X if (n < 0 || n >= last) {
- X current = histptr;
- X curpos = last;
- X return last;
- X } else {
- X current = &history[n];
- X curpos = n;
- X return n;
- X }
- X}
- X
- X/*
- X * This will become unecessary if histget is modified to allow
- X * searching from positions other than the end, and in either
- X * direction.
- X */
- Xchar *
- Xfindhist(start, fwd, str)
- X int start;
- X int fwd;
- X char *str;
- X{
- X char **hp = NULL;
- X int pos = start;
- X char *line, *last;
- X
- X /* XXX check that we are valid after this */
- X if (fwd)
- X pos++;
- X else
- X pos--;
- X histnum(pos);
- X line = *histpos();
- X do {
- X last = line;
- X if (strstr(line, str) != 0) {
- X /* keep position current */
- X return (line);
- X }
- X if (fwd)
- X pos++;
- X else
- X pos--;
- X histnum(pos);
- X line = *histpos();
- X } while (line && *line && line != last && pos>0);
- X
- X histnum(start);
- X if (pos <= 0)
- X return (char*)-1; /* TODO */
- X return NULL;
- X}
- END_OF_FILE
- if test 7391 -ne `wc -c <'sh/history.c'`; then
- echo shar: \"'sh/history.c'\" unpacked with wrong size!
- fi
- # end of 'sh/history.c'
- fi
- if test -f 'sh/main.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sh/main.c'\"
- else
- echo shar: Extracting \"'sh/main.c'\" \(8586 characters\)
- sed "s/^X//" >'sh/main.c' <<'END_OF_FILE'
- X/*
- X * startup, main loop, enviroments and error handling
- X */
- X
- X#ifndef lint
- Xstatic char *RCSid = "$Id: main.c,v 3.3 89/03/27 15:51:39 egisin Exp $";
- Xstatic char *sccs_id = "@(#)main.c 1.3 91/11/09 15:34:27 (sjg)";
- X#endif
- X
- X#define Extern /* define Externs in sh.h */
- X
- X#include <stddef.h>
- X#include <stdlib.h>
- X#include <stdio.h>
- X#include <string.h>
- X#include <unistd.h>
- X#include <fcntl.h>
- X#include <signal.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include <time.h>
- X#include "sh.h"
- X#include "lex.h"
- X#include "tree.h"
- X#include "table.h"
- X
- X/*
- X * global data
- X */
- X
- XArea aperm;
- X
- Xstatic void reclaim ARGS((void));
- X
- X/*
- X * shell initialization
- X */
- X
- Xstatic char initifs [] = "IFS= \t\n"; /* must be R/W */
- X
- Xstatic Const char initsubs [] =
- X#ifdef sun /* sun's don't have a real /bin */
- X "${SHELL:=/bin/sh} ${PATH:=/usr/bin:/usr/ucb:.} ${HOME:=/} ${PS1:=$ } ${PS2:=> } ${MAILCHECK:=600}";
- X#else
- X "${SHELL:=/bin/sh} ${PATH:=/bin:/usr/bin:.} ${HOME:=/} ${PS1:=$ } ${PS2:=> } ${MAILCHECK:=600}";
- X#endif
- X
- Xstatic Const char *initcoms [] = {
- X "cd", ".", NULL, /* set up $PWD */
- X "typeset", "-x", "SHELL", "PATH", "HOME", NULL,
- X "typeset", "-r", "PWD", "OLDPWD", NULL,
- X "typeset", "-i", "SECONDS=0", "OPTIND=1", NULL,
- X "alias",
- X "integer=typeset -i", "pwd=print -r \"$PWD\"",
- X "history=fc -l", "r=fc -e -", "nohup=nohup ",
- X "login=exec login", "newgrp=exec newgrp",
- X "type=whence -v", "functions=typeset -f",
- X "echo=print", "true=:", "false=let", "[=\\[", NULL,
- X NULL
- X};
- X
- X#ifdef USE_TRACE
- X/*
- X * use SIGUSR1 to bump up Trace_level
- X * use SIGUSR2 to clear Trace_level
- X */
- Xvoid
- Xset_TraceLev(sig)
- X int sig;
- X{
- X switch(sig)
- X {
- X case SIGUSR1:
- X Trace_level++;
- X break;
- X case SIGUSR2:
- X Trace_level = 0;
- X break;
- X }
- X if (sig > 0)
- X (void) signal(sig, set_TraceLev);
- X return;
- X}
- X#endif
- X
- Xmain(argc, argv, envp)
- X int argc;
- X register char **argv;
- X char **envp;
- X{
- X register int i;
- X register char *arg;
- X int cflag = 0, qflag = 0, fflag = 0;
- X char *name;
- X register Source *s;
- X register struct block *l = &globals;
- X register char **wp0, **wp;
- X extern char ksh_version [];
- X extern time_t time();
- X
- X ainit(&aperm); /* initialize permanent Area */
- X
- X /* set up base enviroment */
- X e.type = E_NONE;
- X ainit(&e.area);
- X e.loc = l;
- X e.savefd = NULL;
- X e.oenv = NULL;
- X
- X initctypes();
- X
- X /* open file streams for fd's 0,1,2 */
- X fopenshf(0); fopenshf(1); fopenshf(2);
- X
- X /* set up variable and command dictionaries */
- X newblock(); /* set up global l->vars and l->funs */
- X tinit(&commands, APERM);
- X tinit(&builtins, APERM);
- X tinit(&lexicals, APERM);
- X tinit(&homedirs, APERM);
- X
- X /* import enviroment */
- X if (envp != NULL)
- X for (wp = envp; *wp != NULL; wp++)
- X import(*wp);
- X
- X kshpid = getpid();
- X typeset(initifs, 0, 0); /* for security */
- X typeset(ksh_version, 0, 0); /* RDONLY */
- X
- X#ifdef USE_TRACE
- X (void) signal(SIGUSR1, set_TraceLev);
- X (void) signal(SIGUSR2, set_TraceLev);
- X _TRACE(0, ("Traces enabled.")); /* allow _TRACE to setup */
- X#endif
- X
- X /* define shell keywords */
- X keywords();
- X
- X /* define built-in commands */
- X for (i = 0; shbuiltins[i].name != NULL; i++)
- X builtin(shbuiltins[i].name, shbuiltins[i].func);
- X for (i = 0; kshbuiltins[i].name != NULL; i++)
- X builtin(kshbuiltins[i].name, kshbuiltins[i].func);
- X
- X /* assign default shell variable values */
- X substitute(initsubs, 0);
- X setint(typeset("PPID", INTEGER, 0), (long) getppid());
- X typeset("PPID", RDONLY, 0);
- X setint(typeset("RANDOM", INTEGER, 0), (long) time((time_t *)0));
- X /* execute initialization statements */
- X for (wp0 = (char**) initcoms; *wp0 != NULL; wp0 = wp+1) {
- X /* copy because the alias initializers are readonly */
- X for (wp = wp0; *wp != NULL; wp++)
- X *wp = strsave(*wp, ATEMP);
- X shcomexec(wp0);
- X }
- X afreeall(ATEMP);
- X
- X if (geteuid() == 0)
- X setstr(global("PS1"), "# ");
- X
- X s = pushs(SFILE);
- X s->u.file = stdin;
- X cflag = 0;
- X name = *argv++;
- X
- X /* what a bloody mess */
- X if (--argc >= 1) {
- X if (argv[0][0] == '-' && argv[0][1] != '\0') {
- X for (arg = argv[0]+1; *arg; arg++)
- X switch (*arg) {
- X case 'c':
- X cflag = 1;
- X if (--argc > 0) {
- X s->type = SSTRING;
- X s->str = *++argv;
- X }
- X break;
- X
- X case 'q':
- X qflag = 1;
- X break;
- X
- X default:
- X if (*arg>='a' && *arg<='z')
- X flag[FLAG(*arg)]++;
- X }
- X } else {
- X argv--;
- X argc++;
- X }
- X if (s->type == SFILE && --argc > 0 && !flag[FSTDIN]) {
- X if ((s->u.file = fopen(*++argv, "r")) == NULL)
- X errorf("%s: cannot open\n", *argv);
- X fflag = 1;
- X s->file = name = *argv;
- X argc--;
- X fileno(s->u.file) = savefd(fileno(s->u.file));
- X setvbuf(s->u.file, (char *)NULL, _IOFBF, BUFSIZ);
- X }
- X }
- X
- X if (s->type == SFILE) {
- X if (fileno(s->u.file) == 0)
- X flag[FSTDIN] = 1;
- X if (isatty(0) && isatty(1) && !cflag && !fflag)
- X flag[FTALKING] = 1;
- X if (flag[FTALKING] && flag[FSTDIN])
- X s->type = STTY;
- X }
- X if (s->type == STTY) {
- X ttyfd = fcntl(0, F_DUPFD, FDBASE);
- X (void) fcntl(ttyfd, F_SETFD, FD_CLEXEC);
- X#ifdef EMACS
- X x_init_emacs();
- X#endif
- X }
- X
- X /* initialize job control */
- X j_init();
- X
- X if (!qflag)
- X ignoresig(SIGQUIT);
- X
- X l->argv = argv;
- X l->argc = argc;
- X l->argv[0] = name;
- X resetopts();
- X
- X if (name[0] == '-') {
- X flag[FTALKING] = 1;
- X (void) include("/etc/profile");
- X (void) include(".profile");
- X }
- X
- X /* include $ENV */
- X arg = substitute(strval(global("ENV")), DOTILDE);
- X if (*arg != '\0')
- X (void) include(arg);
- X
- X if (flag[FTALKING]) {
- X signal(SIGTERM, trapsig);
- X ignoresig(SIGINT);
- X } else
- X flag[FHASHALL] = 1;
- X
- X#ifdef JOBS /* todo: could go before includes? */
- X if (s->type == STTY) {
- X flag[FMONITOR] = 1;
- X j_change();
- X }
- X#endif
- X
- X argc = shell(s);
- X leave(argc);
- X}
- X
- Xint
- Xinclude(name)
- X register char *name;
- X{
- X register FILE *f;
- X register Source *s;
- X
- X if (strcmp(name, "-") != 0) {
- X f = fopen(name, "r");
- X if (f == NULL)
- X return 0;
- X /* todo: the savefd doesn't get popped */
- X fileno(f) = savefd(fileno(f)); /* questionable */
- X setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
- X } else
- X f = stdin;
- X s = pushs(SFILE);
- X s->u.file = f;
- X s->file = name;
- X /*return*/ shell(s);
- X if (f != stdin)
- X fclose(f);
- X return 1;
- X}
- X
- Xint
- Xcommand(comm)
- X register char *comm;
- X{
- X register Source *s;
- X
- X s = pushs(SSTRING);
- X s->str = comm;
- X return shell(s);
- X}
- X
- X/*
- X * run the commands from the input source, returning status.
- X */
- Xint
- Xshell(s)
- X Source *s; /* input source */
- X{
- X struct op *t;
- X Volatile int attempts = 13;
- X Volatile int wastty;
- X Volatile int reading = 0;
- X extern void mcheck();
- X
- X newenv(E_PARSE);
- X e.interactive = 1;
- X exstat = 0;
- X if (setjmp(e.jbuf)) {
- X /*shellf("<unwind>");*/
- X if (trap) /* pending SIGINT */
- X shellf("\n");
- X if (reading && s->type == STTY && s->line)
- X s->line--;
- X sigtraps[SIGINT].set = 0;
- X }
- X
- X while (1) {
- X if (trap)
- X runtraps();
- X if (flag[FTALKING])
- X signal(SIGINT, trapsig);
- X
- X if (s->next == NULL)
- X s->echo = flag[FVERBOSE];
- X
- X j_notify();
- X
- X if ((wastty = (s->type == STTY)) || s->type == SHIST) {
- X prompt = substitute(strval(global("PS1")), 0);
- X mcheck();
- X }
- X
- X reading = 1;
- X t = compile(s);
- X reading = 0;
- X j_reap();
- X if (t != NULL && t->type == TEOF)
- X if (wastty && flag[FIGNEOF] && --attempts > 0) {
- X shellf("Use `exit'\n");
- X s->type = STTY;
- X continue;
- X }
- X else
- X break;
- X flushshf(2); /* flush -v output */
- X
- X if (!flag[FNOEXEC] || s->type == STTY)
- X execute(t, 0);
- X
- X reclaim();
- X }
- X Error:
- X quitenv();
- X return exstat;
- X}
- X
- Xvoid
- Xleave(rv)
- X int rv;
- X{
- X if (e.type == E_TCOM && e.oenv != NULL) /* exec'd command */
- X unwind();
- X runtrap(&sigtraps[0]);
- X j_exit();
- X exit(rv);
- X /* NOTREACHED */
- X}
- X
- Xerror()
- X{
- X if (flag[FERREXIT] || !flag[FTALKING])
- X leave(1);
- X unwind();
- X}
- X
- X/* return to closest error handler or shell(), exit if none found */
- Xunwind()
- X{
- X while (1)
- X switch (e.type) {
- X case E_NONE:
- X leave(1);
- X /* NOTREACHED */
- X case E_PARSE:
- X longjmp(e.jbuf, 1);
- X /* NOTREACHED */
- X case E_ERRH:
- X longjmp(e.jbuf, 1);
- X /* NOTREACHED */
- X default:
- X quitenv();
- X break;
- X }
- X}
- X
- Xnewenv(type)
- X{
- X register struct env *ep;
- X
- X ep = (struct env *) alloc(sizeof(*ep), ATEMP);
- X *ep = e;
- X ainit(&e.area);
- X e.type = type;
- X e.oenv = ep;
- X e.savefd = NULL;
- X e.temps = NULL;
- X}
- X
- Xquitenv()
- X{
- X register struct env *ep;
- X register int fd;
- X
- X if ((ep = e.oenv) == NULL)
- X exit(exstat); /* exit child */
- X if (e.loc != ep->loc)
- X popblock();
- X if (e.savefd != NULL)
- X for (fd = 0; fd < NUFILE; fd++)
- X restfd(fd, e.savefd[fd]);
- X reclaim();
- X e = *ep;
- X}
- X
- X/* remove temp files and free ATEMP Area */
- Xstatic void
- Xreclaim()
- X{
- X register struct temp *tp;
- X
- X for (tp = e.temps; tp != NULL; tp = tp->next)
- X remove(tp->name);
- X e.temps = NULL;
- X afreeall(&e.area);
- X}
- X
- Xvoid
- Xaerror(ap, msg)
- X Area *ap;
- X Const char *msg;
- X{
- X errorf("alloc internal error: %s\n", msg);
- X}
- X
- END_OF_FILE
- if test 8586 -ne `wc -c <'sh/main.c'`; then
- echo shar: \"'sh/main.c'\" unpacked with wrong size!
- fi
- # end of 'sh/main.c'
- fi
- if test -f 'sh/tree.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sh/tree.c'\"
- else
- echo shar: Extracting \"'sh/tree.c'\" \(9120 characters\)
- sed "s/^X//" >'sh/tree.c' <<'END_OF_FILE'
- X/*
- X * command tree climbing
- X */
- X
- Xstatic char *RCSid = "$Id: tree.c,v 3.2 89/03/27 15:52:13 egisin Exp $";
- X
- X#include <stddef.h>
- X#include <string.h>
- X#include <stdio.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include <varargs.h>
- X#include "sh.h"
- X#include "tree.h"
- X
- X#define FSTRING (FILE*)NULL
- X
- Xstatic int tputc ARGS((int c, FILE *f));
- Xstatic void tputC ARGS((int c, FILE *f));
- Xstatic void tputS ARGS((char *wp, FILE *f));
- X
- X/*
- X * print a command tree
- X */
- X
- Xvoid
- Xptree(t, f)
- X register struct op *t;
- X register FILE *f;
- X{
- X register char **w;
- X struct ioword **ioact;
- X struct op *t1;
- X
- X Chain:
- X if (t == NULL)
- X return;
- X switch (t->type) {
- X case TCOM:
- X for (w = t->vars; *w != NULL; )
- X fptreef(f, "%S ", *w++);
- X for (w = t->args; *w != NULL; )
- X fptreef(f, "%S ", *w++);
- X break;
- X case TEXEC:
- X t = t->left;
- X goto Chain;
- X case TPAREN:
- X fptreef(f, "(%T)", t->left);
- X break;
- X case TPIPE:
- X fptreef(f, "%T| ", t->left);
- X t = t->right;
- X goto Chain;
- X case TLIST:
- X fptreef(f, "%T", t->left);
- X fptreef(f, "%;");
- X t = t->right;
- X goto Chain;
- X case TOR:
- X case TAND:
- X fptreef(f, "%T", t->left);
- X fptreef(f, "%s %T", (t->type==TOR) ? "||" : "&&", t->right);
- X break;
- X case TFOR:
- X fptreef(f, "for %s ", t->str);
- X if (t->vars != NULL) {
- X fptreef(f, "in ");
- X for (w = t->vars; *w; )
- X fptreef(f, "%S ", *w++);
- X fptreef(f, "%;");
- X }
- X fptreef(f, "do %T", t->left);
- X fptreef(f, "%;done ");
- X break;
- X case TCASE:
- X fptreef(f, "case %S in%;", t->str);
- X for (t1 = t->left; t1 != NULL; t1 = t1->right) {
- X fptreef(f, "(");
- X for (w = t1->vars; *w != NULL; w++) {
- X fptreef(f, "%S", *w);
- X fptreef(f, "%c", (w[1] != NULL) ? '|' : ')');
- X }
- X fptreef(f, " %T;;%;", t1->left);
- X }
- X fptreef(f, "esac ");
- X break;
- X case TIF:
- X fptreef(f, "if %T", t->left);
- X fptreef(f, "%;");
- X t = t->right;
- X if (t->left != NULL) {
- X fptreef(f, "then %T", t->left);
- X fptreef(f, "%;");
- X }
- X if (t->right != NULL) {
- X fptreef(f, "else %T", t->right);
- X fptreef(f, "%;");
- X }
- X fptreef(f, "fi ");
- X break;
- X case TWHILE:
- X case TUNTIL:
- X fptreef(f, "%s %T",
- X (t->type==TWHILE) ? "while" : "until",
- X t->left);
- X fptreef(f, "%;do %T", t->right);
- X fptreef(f, "%;done ");
- X break;
- X case TBRACE:
- X fptreef(f, "{%;%T", t->left);
- X fptreef(f, "%;} ");
- X break;
- X case TASYNC:
- X fptreef(f, "%T&", t->left);
- X break;
- X case TFUNCT:
- X fptreef(f, "function %s %T", t->str, t->left);
- X break;
- X case TTIME:
- X fptreef(f, "time %T", t->left);
- X break;
- X default:
- X fptreef(f, "<botch>");
- X break;
- X }
- X if ((ioact = t->ioact) != NULL)
- X while (*ioact != NULL)
- X pioact(f, *ioact++);
- X}
- X
- Xpioact(f, iop)
- X register FILE *f;
- X register struct ioword *iop;
- X{
- X register int flag = iop->flag;
- X if (iop->unit > 1)
- X fptreef(f, "%c", '0' + iop->unit );
- X
- X switch(flag&IOTYPE) {
- X case IOREAD:
- X fptreef(f, "< ");
- X break;
- X case IOHERE:
- X if (flag&IOSKIP)
- X fptreef(f, "<<- ");
- X else
- X fptreef(f, "<< ");
- X if (!(flag&IOEVAL))
- X fptreef(f, "'");
- X break;
- X case IOCAT:
- X fptreef(f, ">> ");
- X break;
- X case IOWRITE:
- X if (flag&IOCLOB)
- X fptreef(f, ">! ");
- X else
- X fptreef(f, "> ");
- X break;
- X case IODUP: /* Needs help */
- X if (iop->unit == 0)
- X fptreef(f, "<&");
- X else
- X fptreef(f, ">&");
- X break;
- X }
- X
- X if ((flag&IOTYPE) == IOHERE) {
- X if (flag&IOEVAL)
- X fptreef(f, "%s ", iop->name);
- X else
- X fptreef(f, "%s' ", iop->name);
- X } else {
- X fptreef(f, "%S ", iop->name);
- X }
- X}
- X
- X
- X/*
- X * variants of fputc, fputs for ptreef and snptreef
- X */
- X
- Xstatic char *snpf_s; /* snptreef string */
- Xstatic int snpf_n; /* snptreef length */
- X
- Xstatic int
- Xtputc(c, f)
- X int c;
- X register FILE *f;
- X{
- X if (f != NULL)
- X putc(c, f);
- X else
- X if (--snpf_n >= 0)
- X *snpf_s++ = c;
- X return c;
- X}
- X
- Xstatic void
- XtputC(c, f)
- X register int c;
- X register FILE *f;
- X{
- X if ((c&0x60) == 0) { /* C0|C1 */
- X tputc((c&0x80) ? '$' : '^', f);
- X tputc((c&0x7F|0x40), f);
- X } else if ((c&0x7F) == 0x7F) { /* DEL */
- X tputc((c&0x80) ? '$' : '^', f);
- X tputc('?', f);
- X } else
- X tputc(c, f);
- X}
- X
- Xstatic void
- XtputS(wp, f)
- X register char *wp;
- X register FILE *f;
- X{
- X register int c, quoted=0;
- X
- X while (1)
- X switch ((c = *wp++)) {
- X case EOS:
- X return;
- X case CHAR:
- X tputC(*wp++, f);
- X break;
- X case QCHAR:
- X if (!quoted)
- X tputc('\\', f);
- X tputC(*wp++, f);
- X break;
- X case OQUOTE:
- X quoted = 1;
- X tputc('"', f);
- X break;
- X case CQUOTE:
- X quoted = 0;
- X tputc('"', f);
- X break;
- X case OSUBST:
- X tputc('$', f);
- X tputc('{', f);
- X while ((c = *wp++) != 0)
- X tputc(c, f);
- X if (*wp != CSUBST)
- X tputC(*wp++, f);
- X break;
- X case CSUBST:
- X tputc('}', f);
- X break;
- X case COMSUB:
- X tputc('$', f);
- X tputc('(', f);
- X while (*wp != 0)
- X tputC(*wp++, f);
- X tputc(')', f);
- X break;
- X }
- X}
- X
- X/* TODO: use varargs properly */
- X
- X/* VARARGS */ int
- Xfptreef(f, va_alist) va_dcl
- X register FILE *f;
- X{
- X va_list va;
- X char *fmt;
- X
- X va_start(va);
- X fmt = va_arg(va, char *);
- X vfptreef(f, fmt, va);
- X va_end(va);
- X return 0;
- X}
- X
- X/* VARARGS */ int
- Xsnptreef(s, n, va_alist) va_dcl
- X char *s;
- X int n;
- X{
- X va_list va;
- X char *fmt;
- X
- X snpf_s = s;
- X snpf_n = n;
- X va_start(va);
- X fmt = va_arg(va, char *);
- X vfptreef(FSTRING, fmt, va);
- X tputc('\0', FSTRING);
- X va_end(va);
- X return 0;
- X}
- X
- Xvfptreef(f, fmt, va)
- X register FILE *f;
- X register char *fmt;
- X register va_list va;
- X{
- X register int c;
- X
- X while ((c = *fmt++))
- X if (c == '%') {
- X register long n;
- X register char *p;
- X int neg;
- X
- X switch ((c = *fmt++)) {
- X case 'c':
- X tputc(va_arg(va, int), f);
- X break;
- X case 's':
- X p = va_arg(va, char *);
- X while (*p)
- X tputc(*p++, f);
- X break;
- X case 'S': /* word */
- X p = va_arg(va, char *);
- X tputS(p, f);
- X break;
- X case 'd': case 'u': /* decimal */
- X n = (c == 'd') ? va_arg(va, int) : va_arg(va, unsigned int);
- X neg = c=='d' && n<0;
- X p = ulton((neg) ? -n : n, 10);
- X if (neg)
- X *--p = '-';
- X while (*p)
- X tputc(*p++, f);
- X break;
- X case 'T': /* format tree */
- X ptree(va_arg(va, struct op *), f);
- X break;
- X case ';': /* newline or ; */
- X p = (f == FSTRING) ? "; " : "\n";
- X while (*p)
- X tputc(*p++, f);
- X break;
- X default:
- X tputc(c, f);
- X break;
- X }
- X } else
- X tputc(c, f);
- X}
- X
- X/*
- X * copy tree (for function definition)
- X */
- X
- Xstatic struct ioword **iocopy();
- X
- Xstruct op *
- Xtcopy(t, ap)
- X register struct op *t;
- X Area *ap;
- X{
- X register struct op *r;
- X register char **tw, **rw;
- X
- X if (t == NULL)
- X return NULL;
- X
- X r = (struct op *) alloc(sizeof(struct op), ap);
- X
- X r->type = t->type;
- X
- X /* this will copy function and for identifiers quite accidently */
- X r->str = (t->str == NULL) ? NULL : wdcopy(t->str, ap);
- X
- X if (t->vars == NULL)
- X r->vars = NULL;
- X else {
- X for (tw = t->vars; *tw++ != NULL; )
- X ;
- X rw = r->vars = (char **)
- X alloc((int)(tw - t->vars) * sizeof(*tw), ap);
- X for (tw = t->vars; *tw != NULL; )
- X *rw++ = wdcopy(*tw++, ap);
- X *rw = NULL;
- X }
- X
- X if (t->args == NULL)
- X r->args = NULL;
- X else {
- X for (tw = t->args; *tw++ != NULL; )
- X ;
- X rw = r->args = (char **)
- X alloc((int)(tw - t->args) * sizeof(*tw), ap);
- X for (tw = t->args; *tw != NULL; )
- X *rw++ = wdcopy(*tw++, ap);
- X *rw = NULL;
- X }
- X
- X r->ioact = (t->ioact == NULL) ? NULL : iocopy(t->ioact, ap);
- X
- X r->left = tcopy(t->left, ap);
- X r->right = tcopy(t->right, ap);
- X
- X return r;
- X}
- X
- Xchar *
- Xwdcopy(wp, ap)
- X char *wp;
- X Area *ap;
- X{
- X size_t len = wdscan(wp, EOS) - wp;
- X return memcpy(alloc(len, ap), wp, len);
- X}
- X
- X/* return the position of prefix c in wp plus 1 */
- Xchar *
- Xwdscan(wp, c)
- X register char *wp;
- X register int c;
- X{
- X register int nest = 0;
- X
- X while (1)
- X switch (*wp++) {
- X case EOS:
- X return wp;
- X case CHAR:
- X case QCHAR:
- X wp++;
- X break;
- X case OQUOTE:
- X case CQUOTE:
- X break;
- X case OSUBST:
- X nest++;
- X while (*wp++ != 0)
- X ;
- X if (*wp != CSUBST)
- X wp++;
- X break;
- X case CSUBST:
- X if (c == CSUBST && nest == 0)
- X return wp;
- X nest--;
- X break;
- X case COMSUB:
- X while (*wp++ != 0)
- X ;
- X break;
- X }
- X}
- X
- Xstatic struct ioword **
- Xiocopy(iow, ap)
- X register struct ioword **iow;
- X Area *ap;
- X{
- X register struct ioword **ior;
- X register int i;
- X
- X for (ior = iow; *ior++ != NULL; )
- X ;
- X ior = (struct ioword **) alloc((int)(ior - iow) * sizeof(*ior), ap);
- X
- X for (i = 0; iow[i] != NULL; i++) {
- X register struct ioword *p, *q;
- X
- X p = iow[i];
- X q = (struct ioword *) alloc(sizeof(*p), ap);
- X ior[i] = q;
- X *q = *p;
- X if (p->name != NULL)
- X q->name = wdcopy(p->name, ap);
- X }
- X ior[i] = NULL;
- X
- X return ior;
- X}
- X
- X/*
- X * free tree (for function definition)
- X */
- X
- Xstatic void iofree();
- X
- Xvoid
- Xtfree(t, ap)
- X register struct op *t;
- X Area *ap;
- X{
- X register char **w;
- X
- X if (t == NULL)
- X return;
- X
- X if (t->str != NULL)
- X afree((Void*)t->str, ap);
- X
- X if (t->vars != NULL) {
- X for (w = t->vars; *w != NULL; w++)
- X afree((Void*)*w, ap);
- X afree((Void*)t->vars, ap);
- X }
- X
- X if (t->args != NULL) {
- X for (w = t->args; *w != NULL; w++)
- X afree((Void*)*w, ap);
- X afree((Void*)t->args, ap);
- X }
- X
- X if (t->ioact != NULL)
- X iofree(t->ioact, ap);
- X
- X tfree(t->left, ap);
- X tfree(t->right, ap);
- X
- X afree((Void*)t, ap);
- X}
- X
- Xstatic void
- Xiofree(iow, ap)
- X struct ioword **iow;
- X Area *ap;
- X{
- X register struct ioword **iop;
- X register struct ioword *p;
- X
- X for (iop = iow; (p = *iop++) != NULL; ) {
- X if (p->name != NULL)
- X afree((Void*)p->name, ap);
- X afree((Void*)p, ap);
- X }
- X}
- X
- END_OF_FILE
- if test 9120 -ne `wc -c <'sh/tree.c'`; then
- echo shar: \"'sh/tree.c'\" unpacked with wrong size!
- fi
- # end of 'sh/tree.c'
- fi
- if test -f 'std/stdc/stdio.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'std/stdc/stdio.c'\"
- else
- echo shar: Extracting \"'std/stdc/stdio.c'\" \(301 characters\)
- sed "s/^X//" >'std/stdc/stdio.c' <<'END_OF_FILE'
- X/*
- X * Emulation of misc. ANSI C stdio functions
- X */
- X
- X/* $Header */
- X
- X#include <stdio.h>
- X
- X#if 1
- Xint
- Xremove(name)
- X Const char *name;
- X{
- X return unlink(name);
- X}
- X#endif
- X
- X#if _V7
- Xint
- Xrename(oname, nname)
- X Const char *oname, *nname;
- X{
- X return link(oname, nname) == 0 && unlink(oname) == 0 ? 0 : -1;
- X}
- X#endif
- X
- END_OF_FILE
- if test 301 -ne `wc -c <'std/stdc/stdio.c'`; then
- echo shar: \"'std/stdc/stdio.c'\" unpacked with wrong size!
- fi
- # end of 'std/stdc/stdio.c'
- fi
- echo shar: End of archive 5 \(of 9\).
- cp /dev/null ark5isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 9 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-